-
Preprocessor directives are lines included in the code of programs preceded by a hash sign (
#). -
They extend only across a single line of code. As soon as a newline character is found, the preprocessor directive is ends. No semicolon (
;) is expected at the end of a preprocessor directive. The only way a preprocessor directive can extend through more than one line is by preceding the newline character at the end of the line by a backslash (\). -
General explanation by Casey: Handmade Hero#Ep 11 .
#include
-
When the preprocessor finds an
#includedirective it replaces it by the entire content of the specified header or file. -
There are two ways to use
#include:
#include <header>
#include "file"
-
In the first case, a header is specified between angle-brackets
<>. This is used to include headers provided by the implementation, such as the headers that compose the standard library (iostream, string,...). Whether the headers are actually files or exist in some other form is implementation-defined, but in any case they shall be properly included with this directive. -
The syntax used in the second
#includeuses quotes, and includes a file. The file is searched for in an implementation-defined manner, which generally includes the current path. In the case that the file is not found, the compiler interprets the directive as a header inclusion, just as if the quotes ("") were replaced by angle-brackets (<>).
#pragma
-
This directive is used to specify diverse options to the compiler. These options are specific for the platform and the compiler you use. Consult the manual or the reference of your compiler for more information on the possible parameters that you can define with
#pragma. -
If the compiler does not support a specific argument for
#pragma, it is ignored - no syntax error is generated. -
The name pragma, in programming, it implies something practical or action-oriented.
#define
and
#undefine
-
Syntax:
#define identifier replacement#undef identifier -
It replaces any occurrence of identifier in the rest of the code by replacement. This replacement can be an expression, a statement, a block or simply anything. The preprocessor does not understand C++ proper, it simply replaces any occurrence of identifier by replacement.
-
A macro lasts until it is undefined with the #undef preprocessor directive.
#define TABLE_SIZE 100
int table1[TABLE_SIZE];
#undef TABLE_SIZE
#define TABLE_SIZE 200
int table2[TABLE_SIZE];
Function Macros
#define MIN(a, b) (a < b ? a : b)
-
Function macro definitions accept two special operators (
#and##) in the replacement sequence: -
The operator
#, followed by a parameter name, is replaced by a string literal that contains the argument passed (as if enclosed between double quotes):#define str(x) #x cout << str(test);-
This would be translated into:
cout << "test"; -
-
The operator
##concatenates two arguments leaving no blank spaces between them:#define glue(a,b) a ## b glue(c,out) << "test";-
This would also be translated into:
cout << "test"; -
Conditional inclusions (
#ifdef
,
#ifndef,
#if
,
#endif
,
#else
and
#elif`)
-
These directives allow to include or discard part of the code of a program if a certain condition is met.
-
#ifdefallows a section of a program to be compiled only if the macro that is specified as the parameter has been defined, no matter which its value is:#ifdef TABLE_SIZE int table[TABLE_SIZE]; #endif -
#ifndefserves for the exact opposite: the code between#ifndefand#endifdirectives is only compiled if the specified identifier has not been previously defined:#ifndef TABLE_SIZE #define TABLE_SIZE 100 #endif int table[TABLE_SIZE]; -
The
#if,#elseand#elif(i.e., "else if") directives serve to specify some condition to be met in order for the portion of code they surround to be compiled:#if TABLE_SIZE>200 #undef TABLE_SIZE #define TABLE_SIZE 200 #elif TABLE_SIZE<50 #undef TABLE_SIZE #define TABLE_SIZE 50 #else #undef TABLE_SIZE #define TABLE_SIZE 100 #endif int table[TABLE_SIZE];-
Notice how the entire structure of
#if,#elifand#elsechained directives ends with#endif.
-
-
Alternative syntax:
#if defined ARRAY_SIZE #define TABLE_SIZE ARRAY_SIZE #elif !defined BUFFER_SIZE #define TABLE_SIZE 128 #else #define TABLE_SIZE BUFFER_SIZE #endif
#line
-
The
#linedirective allows us to control both things, the line numbers within the code files as well as the file name that we want that appears when an error takes place. -
Syntax:
#line number "filename"
#line 20 "assigning variable"
int a?;
-
This code will generate an error that will be shown as error in file "assigning variable", line 20.
#error
-
This directive aborts the compilation process when it is found, generating a compilation error that can be specified as its parameter:
-
Syntax:
#error message
#ifndef __cplusplus
#error A C++ compiler is required!
#endif
Predefined Macros
-
Always defined:
-
__LINE__-
Integer value representing the current line in the source code file being compiled.
-
-
__FILE__-
A string literal containing the presumed name of the source file being compiled.
-
-
__DATE__-
A string literal in the form "Mmm dd yyyy" containing the date in which the compilation process began.
-
-
__TIME__-
A string literal in the form "hh:mm:ss" containing the time at which the compilation process began.
-
-
__cplusplus-
An integer value. All C++ compilers have this constant defined to some value. Its value depends on the version of the standard supported by the compiler:
-
199711L: ISO C++ 1998/2003
-
201103L: ISO C++ 2011
-
-
Non conforming compilers define this constant as some value at most five digits long. Note that many compilers are not fully conforming and thus will have this constant defined as neither of the values above.
-
-
__STDC_HOSTED__-
1 if the implementation is a hosted implementation (with all standard headers available)
-
0 otherwise.
-
-
-
Optionally defined:
-
__STDC__-
In C: if defined to 1, the implementation conforms to the C standard.
-
In C++: Implementation defined.
-
-
__STDC_VERSION__-
In C:
-
199401L: ISO C 1990, Ammendment 1
-
199901L: ISO C 1999
-
201112L: ISO C 2011
-
-
In C++: Implementation defined.
-
-
__STDC_MB_MIGHT_NEQ_WC__-
1 if multibyte encoding might give a character a different value in character literals
-
-
__STDC_ISO_10646__-
A value in the form yyyymmL, specifying the date of the Unicode standard followed by the encoding of wchar_t characters
-
-
__STDCPP_STRICT_POINTER_SAFETY__-
1 if the implementation has strict pointer safety (see get_pointer_safety)
-
-
__STDCPP_THREADS__-
1 if the program can have more than one thread
-
-
Macro Patterns / Techniques
X Macros
-
X macros are a technique, not a macro type. The idea is to define a list of items once and reuse it by redefining a helper macro.
do {...} while(0) pattern
-
It's used to create a scope and avoiding the
elsekeyword breaking when using anifwithout{ }, basically; very specific.